package webjoch;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.logging.Logger;

import org.rsbuddy.tabs.Attack;

import webjoch.methods.Rooms;
import webjoch.misc.Constants;
import webjoch.misc.Functions;
import webjoch.process.ProcessRoom;
import webjoch.process.Traveling;
import webjoch.process.strategies.Boss;
import webjoch.wrappers.Door;
import webjoch.wrappers.Link;
import webjoch.wrappers.Room;
import webjoch.wrappers.Task;

import com.rsbuddy.event.events.MessageEvent;
import com.rsbuddy.script.methods.Npcs;
import com.rsbuddy.script.methods.Players;
import com.rsbuddy.script.wrappers.Tile;

public class Dungeon{
	private Tile baseLocation;
	private ArrayList<Task> tasks = new ArrayList<Task>();
	private ArrayList<Door> keyDoors = new ArrayList<Door>();
	private ArrayList<Door> ignoreDoors = new ArrayList<Door>();
	private ArrayList<Room> ignoreRooms = new ArrayList<Room>();
	private ArrayList<Link> map = new ArrayList<Link>();
	private Room currentRoom;
	private Boss boss = null;
	public HashMap<Room, Integer> roomRotations = new HashMap<Room, Integer>();
	private boolean bossTime = false;
	private long msgLvlNeeded = 0;
	
	Logger log = Logger.getLogger("Main.class");
	
	public int loop(){
		int sleep = 1;
		if (baseLocation == null){
			if (Npcs.getNearest(Constants.SMUGLER) == null){
				log.warning("Can't find smugler");
				return -1;
			}
			baseLocation = Npcs.getNearest(Constants.SMUGLER).getLocation();
		}
		if (currentRoom == null || !currentRoom.getArea().contains(Players.getLocal().getLocation())){
			currentRoom = Rooms.getRoom(Players.getLocal().getLocation());
			currentRoom.updateLinks();
			for (Door door : currentRoom.getDoors()){
				if (door.getType() == Door.Type.KEY && door.isLocked() && !Functions.inArray(getKeyDoors(), door)) keyDoors.add(door);
			}
		}
		
		if (Attack.isAutoRetaliateEnabled()){
			Attack.setAutoRetaliate(false);
		}
		
		if (bossTime && getBoss() != null){
			Main.setStatus("Boss time");
			if (!getBoss().getRoom().inRoom()){
				Traveling.travel(getBoss().getRoom().getLocation());
				return 1;
			}
			return getBoss().loop();
		}
		
		ProcessRoom Process = new ProcessRoom(currentRoom);
		if (Process.loop()){
			sleep = Traveling.loop();
		}
		
		return sleep;
	}
	
	public void setBaseLocation(Tile location){
		baseLocation = location;
	}
	
	public void addRoom(Link link){
		System.out.println(link.getRoom().getType());
		map.add(link);
	}
	
	public void removeRoom(Room room){
		for (int i = 0; i < map.size(); i++){
			if (map.get(i).getRoom().getLocation().equals(room.getLocation())){
				map.remove(i);
				removeRoom(room);
				break;
			}
		}		
	}
	
	public void clearMap(){
		map.clear();
	}

	public void addKeyDoor(Door door){
		keyDoors.add(door);
	}
	
	public void removeKeyDoor(Door door){
		for (int i = 0; i < keyDoors.size(); i++){
			if (keyDoors.get(i).getId() == door.getId()){
				keyDoors.remove(i);
				break;
			}
		}
	}
	
	public void setBoss(Boss boss){
		log.info("Boss room founded, boss: "+ boss.getBossType().toString());
		this.boss = boss;
	}
	
	public Boss getBoss(){
		return boss;
	}
	
	public void bossTime(){
		bossTime = true;
	}
	
	public Task[] getTasks(){
		return tasks.toArray(new Task[tasks.size()]);
	}
	
	public void addTask(Task task){
		removeTask(task, false);
		tasks.add(task);
	}
	
	public void addRoomRotation(Room room, int rotation){
		roomRotations.put(room, rotation);
	}
	
	public int getRoomRotation(Room room){
		for (Room roomKey : roomRotations.keySet()){
			if (roomKey.getLocation().equals(room.getLocation())){
				return roomRotations.get(roomKey);
			}
		}
		return -1;
	}
	
	public void addIgnoreDoor(Door door){
		ignoreDoors.add(door);
	}
	
	public boolean shouldIgnoreDoor(Door checkDoor){
		for (Door door : ignoreDoors){
			if (door.getLocation().equals(checkDoor.getLocation())) return true;
		}
		return false;
	}
	
	public void removeTask(Task task, boolean allFromRoom){
		for (int i = 0; i < tasks.size(); i++){
			if (task.getRoom().getLocation().equals(tasks.get(i).getRoom().getLocation())){
				if (tasks.get(i).getNeededItems()[0] == 0 || tasks.get(i).getNeededItems()[0] == task.getNeededItems()[0] || allFromRoom){
					tasks.remove(i);
					removeTask(task, allFromRoom);
					break;
				}
			}
		}
	}
	
	public Link[] getMap(){
		return map.toArray(new Link[map.size()]);
	}
	
	public Door[] getKeyDoors(){
		return keyDoors.toArray(new Door[keyDoors.size()]);
	}
	
	public Tile getBaseLocation(){
		return baseLocation;
	}
	
	public Room getCurrentRoom(){
		return currentRoom;
	}
	
	public long msgLvlNeeded(){
		return msgLvlNeeded;
	}
	
	public void addIgnoreRoom(Room room){
		ignoreRooms.add(room);
	}

	public boolean ignoreRoom(Room room){
		return ignoreRooms.contains(room);
	}
	
	public void stop(String reason){
		log.info("Restart dungeon, reason: "+ reason);
		//TODO leave the dungeon
	}
	
	public void messageReceived(MessageEvent e) {
		if (e.isAutomated()){
			if (e.getMessage().contains("ou need a") && e.getMessage().contains("level")){
				msgLvlNeeded = Main.getRunTime();
			}
		}
	}
}
